/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2020 TELEMATICS LAB, Politecnico di Bari
 *
 * This file is part of 5G-air-simulator
 *
 * 5G-air-simulator is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation;
 *
 * 5G-air-simulator is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with 5G-air-simulator; if not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Alessandro Grassi <alessandro.grassi@poliba.it>
 */


#ifndef GAUSSIANRANDOMVARIABLE_H_
#define GAUSSIANRANDOMVARIABLE_H_

#include <stdint.h>
#include <stdlib.h>
#include "RandomVariable.h"

static double NormCDF[201] =
{
  0.0000, 0.0000, 0.0000, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0002, 0.0002, 0.0002, 0.0003, 0.0003, 0.0003, 0.0004, 0.0005, 0.0005, 0.0006, 0.0007, 0.0008, 0.0009, 0.0010, 0.0012, 0.0013, 0.0015, 0.0018, 0.0020, 0.0023, 0.0026, 0.0029, 0.0033, 0.0037, 0.0041, 0.0047, 0.0052, 0.0059, 0.0066, 0.0073, 0.0082, 0.0091, 0.0102, 0.0113, 0.0125, 0.0139, 0.0154, 0.0170, 0.0188, 0.0207, 0.0228, 0.0250, 0.0274, 0.0301, 0.0329, 0.0359, 0.0392, 0.0427, 0.0465, 0.0505, 0.0548, 0.0594, 0.0643, 0.0694, 0.0749, 0.0808, 0.0869, 0.0934, 0.1003, 0.1075, 0.1151, 0.1230, 0.1314, 0.1401, 0.1492, 0.1587, 0.1685, 0.1788, 0.1894, 0.2005, 0.2119, 0.2236, 0.2358, 0.2483, 0.2611, 0.2743, 0.2877, 0.3015, 0.3156, 0.3300, 0.3446, 0.3594, 0.3745, 0.3897, 0.4052, 0.4207, 0.4364, 0.4522, 0.4681, 0.4840, 0.5000, 0.5160, 0.5319, 0.5478, 0.5636, 0.5793, 0.5948, 0.6103, 0.6255, 0.6406, 0.6554, 0.6700, 0.6844, 0.6985, 0.7123, 0.7257, 0.7389, 0.7517, 0.7642, 0.7764, 0.7881, 0.7995, 0.8106, 0.8212, 0.8315, 0.8413, 0.8508, 0.8599, 0.8686, 0.8770, 0.8849, 0.8925, 0.8997, 0.9066, 0.9131, 0.9192, 0.9251, 0.9306, 0.9357, 0.9406, 0.9452, 0.9495, 0.9535, 0.9573, 0.9608, 0.9641, 0.9671, 0.9699, 0.9726, 0.9750, 0.9772, 0.9793, 0.9812, 0.9830, 0.9846, 0.9861, 0.9875, 0.9887, 0.9898, 0.9909, 0.9918, 0.9927, 0.9934, 0.9941, 0.9948, 0.9953, 0.9959, 0.9963, 0.9967, 0.9971, 0.9974, 0.9977, 0.9980, 0.9982, 0.9985, 0.9987, 0.9988, 0.9990, 0.9991, 0.9992, 0.9993, 0.9994, 0.9995, 0.9995, 0.9996, 0.9997, 0.9997, 0.9997, 0.9998, 0.9998, 0.9998, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 0.9999, 1.0000, 1.0000, 1.0000
};

static double NormValues[201] =
{
  -4.0000, -3.9600, -3.9200, -3.8800, -3.8400, -3.8000, -3.7600, -3.7200, -3.6800, -3.6400, -3.6000, -3.5600, -3.5200, -3.4800, -3.4400, -3.4000, -3.3600, -3.3200, -3.2800, -3.2400, -3.2000, -3.1600, -3.1200, -3.0800, -3.0400, -3.0000, -2.9600, -2.9200, -2.8800, -2.8400, -2.8000, -2.7600, -2.7200, -2.6800, -2.6400, -2.6000, -2.5600, -2.5200, -2.4800, -2.4400, -2.4000, -2.3600, -2.3200, -2.2800, -2.2400, -2.2000, -2.1600, -2.1200, -2.0800, -2.0400, -2.0000, -1.9600, -1.9200, -1.8800, -1.8400, -1.8000, -1.7600, -1.7200, -1.6800, -1.6400, -1.6000, -1.5600, -1.5200, -1.4800, -1.4400, -1.4000, -1.3600, -1.3200, -1.2800, -1.2400, -1.2000, -1.1600, -1.1200, -1.0800, -1.0400, -1.0000, -0.9600, -0.9200, -0.8800, -0.8400, -0.8000, -0.7600, -0.7200, -0.6800, -0.6400, -0.6000, -0.5600, -0.5200, -0.4800, -0.4400, -0.4000, -0.3600, -0.3200, -0.2800, -0.2400, -0.2000, -0.1600, -0.1200, -0.0800, -0.0400,      0, 0.0400, 0.0800, 0.1200, 0.1600, 0.2000, 0.2400, 0.2800, 0.3200, 0.3600, 0.4000, 0.4400, 0.4800, 0.5200, 0.5600, 0.6000, 0.6400, 0.6800, 0.7200, 0.7600, 0.8000, 0.8400, 0.8800, 0.9200, 0.9600, 1.0000, 1.0400, 1.0800, 1.1200, 1.1600, 1.2000, 1.2400, 1.2800, 1.3200, 1.3600, 1.4000, 1.4400, 1.4800, 1.5200, 1.5600, 1.6000, 1.6400, 1.6800, 1.7200, 1.7600, 1.8000, 1.8400, 1.8800, 1.9200, 1.9600, 2.0000, 2.0400, 2.0800, 2.1200, 2.1600, 2.2000, 2.2400, 2.2800, 2.3200, 2.3600, 2.4000, 2.4400, 2.4800, 2.5200, 2.5600, 2.6000, 2.6400, 2.6800, 2.7200, 2.7600, 2.8000, 2.8400, 2.8800, 2.9200, 2.9600, 3.0000, 3.0400, 3.0800, 3.1200, 3.1600, 3.2000, 3.2400, 3.2800, 3.3200, 3.3600, 3.4000, 3.4400, 3.4800, 3.5200, 3.5600, 3.6000, 3.6400, 3.6800, 3.7200, 3.7600, 3.8000, 3.8400, 3.8800, 3.9200, 3.9600, 4.0000
};

static double GetGaussianRandomVariable(double mean=0, double stdDev=1)
{
  double probability = rand()*1.0/RAND_MAX;
  double value;
  for (int i = 0; i < 201; i++)
    {
      if (probability <= (NormCDF[i]+NormCDF[i+1])/2)
        {
          value = NormValues[i] * stdDev + mean;
          break;
        }
    }
  return value;
}

#endif /* GAUSSIANRANDOMVARIABLE_H_ */
